package cn.Aop;

import cn.DynamicDataSource.DataSourceName;
import cn.DynamicDataSource.DynamicDataSourceHolder;
import cn.MetaData.Annotation.ChooseDataSource;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * 数据源路由选择切面类
 */
@Slf4j
@Aspect
@Component
public class ChooseDataSourceAop {


    /**
     * 注解切入点
     */
    @Pointcut("@annotation(cn.MetaData.Annotation.ChooseDataSource) && args(..)")
    private void ChooseDatasourcePointcutByAnnotation() {
    }


    /**
     * 动态数据源选择切面
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Around("ChooseDatasourcePointcutByAnnotation()")
    public Object permission(ProceedingJoinPoint joinPoint) throws Throwable {
        Object target = joinPoint.getTarget();
        Object[] args = joinPoint.getArgs();
        Method method = getMethod(joinPoint, args);

        log.info("动态数据源选择切面");

        //获取数据库名称参数
        ChooseDataSource chooseDataSource = method.getAnnotation(ChooseDataSource.class);
        if (chooseDataSource != null) {
            String dataSourceName = chooseDataSource.dataSourceName();
            //检查数据库名称是否存在
            if (! "".equals(dataSourceName)) {
                DynamicDataSourceHolder.putDataSourceName(dataSourceName);
            } else {
//                DynamicDataSourceHolder.putDataSourceName("PrimaryDatasource");
                DynamicDataSourceHolder.putDataSourceName(DataSourceName.PRIMARYDATASOURCE.getValue());
            }
        }
        return joinPoint.proceed();
    }


    /**
     * 获取关注点 方法信息
     * @param joinPoint
     * @param args
     * @return
     * @throws NoSuchMethodException
     */
    private Method getMethod(ProceedingJoinPoint joinPoint, Object[] args) throws NoSuchMethodException {
        String methodName = joinPoint.getSignature().getName();
        Class clazz = joinPoint.getTarget().getClass();
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            if (methodName.equals(method.getName())) {
                return method;
            }
        }
        return null;
    }
}
